#include <iostream>
#include <string>
#include <memory>
// 优点:易扩展
// 缺点:违背开闭原则，需要修改工厂

// class Fruit
// {
// public:
//     Fruit() {}
//     // 设置为纯虚函数
//     virtual void show() = 0;
// };

// class Apple : public Fruit
// {
// public:
//     Apple() {}
//     void show() override
//     {
//         std::cout << "Apple" << std::endl;
//     }
// };

// class Banana : public Fruit
// {
// public:
//     Banana() {}
//     void show() override
//     {
//         std::cout << "Banana" << std::endl;
//     }
// };

// class Factory
// {
// public:
//     static std::shared_ptr<Fruit> BuildFruit(const std::string& name)
//     {
//         if (name == "Apple")
//             return std::make_shared<Apple>();
//         else if (name == "Banana")
//         {
//             return std::make_shared<Banana>();
//         }
//         return std::shared_ptr<Fruit>();
//     }
// };

// int main()
// {
//     std::shared_ptr<Fruit> apple = Factory::BuildFruit("Apple");
//     apple->show();

//     std::shared_ptr<Fruit> banana = Factory::BuildFruit("Banana");
//     banana->show();
//     return 0;
// }

// 工厂方法模式,维护了开闭原则，但是扩展复杂，代码冗余
// 1.创建水果类  2.继承具体的水果类
// 3.创建水果工厂 4.继承水果常见苹果工厂
//  调用 创建apple指针指向水果类
//  获取指定的水果，调用函数
//  class Fruit
//  {
//  public:
//      Fruit() {}
//      // 设置为纯虚函数
//      virtual void show() = 0;
//  };

// class Apple : public Fruit
// {
// public:
//     Apple() {}
//     void show() override
//     {
//         std::cout << "Apple" << std::endl;
//     }
// };

// class Banana : public Fruit
// {
// public:
//     Banana() {}
//     void show() override
//     {
//         std::cout << "Banana" << std::endl;
//     }
// };

// class FruitFactory{
//     public:
//         virtual std::shared_ptr<Fruit> BuildFruit()=0;
// };

// class AppleFactory :public FruitFactory
// {
//     public:
//         std::shared_ptr<Fruit> BuildFruit() override
//         {
//             return  std::make_shared<Apple>();
//         }
// };

// class BananaFactory :public FruitFactory
// {
//     public:
//         std::shared_ptr<Fruit> BuildFruit() override
//         {
//             return  std::make_shared<Banana>();
//         }
// };

// int main()
// {
//     std::shared_ptr<FruitFactory>  factory(new AppleFactory());
//     auto apple=factory->BuildFruit();
//     apple->show();

//     factory.reset(new BananaFactory());
//     auto banana=factory->BuildFruit();
//     banana->show();

//     return 0;
// }

// 抽象工厂方法，解决了冗余代码的问题

class Fruit
{
public:
    Fruit() {}
    // 设置为纯虚函数
    virtual void show() = 0;
};

class Apple : public Fruit
{
public:
    Apple() {}
    void show() override
    {
        std::cout << "Apple" << std::endl;
    }
};
class Banana : public Fruit
{
public:
    Banana() {}
    void show() override
    {
        std::cout << "Banana" << std::endl;
    }
};

class Animal
{
public:
    virtual void show() = 0;
};

class Dog : public Animal
{
public:
    void show() override
    {
        std::cout << "Dog" << std::endl;
    }
};

class Lamp : public Animal
{
public:
    void show() override
    {
        std::cout << "Lamp" << std::endl;
    }
};

class Factory
{
public:
    virtual std::shared_ptr<Fruit> BuildFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> BuildAnimal(const std::string &name) = 0;
};
class FruitFactory : public Factory
{
public:
    std::shared_ptr<Animal> BuildAnimal(const std::string &name)  override
    {
        return std::shared_ptr<Animal>();
    }
    std::shared_ptr<Fruit> BuildFruit(const std::string &name) override
    {
        if (name == "Apple")
            return std::make_shared<Apple>();
        else if (name == "Banana")
            return std::make_shared<Banana>();
        return std::shared_ptr<Fruit>();
    }
};

class AnimalFactory : public Factory
{
public:
    std::shared_ptr<Fruit> BuildFruit(const std::string &name) override
    {
        return std::shared_ptr<Fruit>();
    }
    std::shared_ptr<Animal> BuildAnimal(const std::string &name) override
    {
        if (name == "Dog")
            return std::make_shared<Dog>();
        else if (name == "Lamp")
            return std::make_shared<Lamp>();
        return std::shared_ptr<Animal>();
    }
};

class FactoryProduce{
    public:
        static std::shared_ptr<Factory> Build(const std::string &name)
        {
            if(name=="水果")
                return std::make_shared<FruitFactory>();
            else if(name=="动物"){
                return std::make_shared<AnimalFactory>();
            }
            return std::shared_ptr<Factory>();
        }
};

int main(){

    std::shared_ptr<Factory> factor=FactoryProduce::Build("动物");
    auto dog=factor->BuildAnimal("Dog");
    dog->show();
    std::shared_ptr<Factory> fruit_factor=FactoryProduce::Build("水果");
    auto apple=fruit_factor->BuildFruit("Apple");
    apple->show();


    return 0;
}
